package com.smart.manager.union.egg.repository;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjectUtil;
import com.smart.common.entities.core.BaseSearch;
import com.smart.common.entities.core.Page;
import com.smart.common.entities.domain.OrderAddress;
import com.smart.manager.member.entities.enums.CoinAccountEvent;
import com.smart.manager.member.entities.models.MemberProfileAccount;
import com.smart.manager.member.entities.views.MemberView;
import com.smart.manager.member.repository.MemberAccountRepository;
import com.smart.manager.member.repository.MemberProfileAddressRepository;
import com.smart.manager.union.egg.body.RUnionEggOrder;
import com.smart.manager.union.egg.enums.EggOrderState;
import com.smart.manager.union.egg.models.UnionEggOrder;
import com.smart.manager.union.egg.models.UnionEggProduct;
import com.smart.manager.union.egg.models.query.QUnionEggOrder;
import com.smart.service.remind.RemindService;
import com.smart.utils.SqlUtil;
import com.smart.wap.bodys.OrderBody;
import com.smart.wap.bodys.EggOrderNotice;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 帮助中心
 *
 * @author leo
 * @date 2023/07/26
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class UnionEggOrderRepository {

    private final UnionEggProductRepository productRepository;
    private final MemberAccountRepository memberAccountRepository;
    private final MemberProfileAddressRepository addressRepository;
    private final RemindService remindService ;

    /**
     * 查询搜索
     *
     * @param search 搜索
     * @return {@link Page}<{@link UnionEggOrder}>
     */
    public Page<UnionEggOrder> pageList(RUnionEggOrder.SearchBody search) {
        QUnionEggOrder query = new QUnionEggOrder();

        Opt.ofBlankAble(search.getKeyword()).ifPresent(x -> query.raw("address::text like '%" + x + "%'  "));
        Opt.ofBlankAble(search.getState()).ifPresent(x -> query.state.eq(x));
        Opt.ofBlankAble(search.getSubmitRange()).ifPresent(x -> {
            LocalDateTime[] ts = SqlUtil.formatDateTimeRange(x);
            query.submitTime.between(ts[0], ts[1]);

        });
        Opt.ofBlankAble(search.getSendRangeRange()).ifPresent(x -> {
            LocalDateTime[] ts = SqlUtil.formatDateTimeRange(x);
            query.submitTime.between(ts[0], ts[1]);

        });

        Opt.ofBlankAble(search.getExpressName()).ifPresent(x -> query.expressName.contains(x));
        Opt.ofBlankAble(search.getExpressCode()).ifPresent(x -> query.expressCode.contains(x));
        query.order().id.desc().setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<UnionEggOrder>().load(query.findPagedList());
    }


    public Page<UnionEggOrder> getMyPageList(Long memberId, BaseSearch search) {

        QUnionEggOrder query = new QUnionEggOrder();

        query.member.id.eq(memberId).order().id.desc().setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<UnionEggOrder>().load(query.findPagedList());

    }


    /**
     * 创建鸡蛋订单
     */
    public void createOrder(Long memberId, Long productId) {

        UnionEggProduct product = productRepository.getOneById(productId);
        Assert.notNull(product, "兑换失败:兑换规格不存在");
        MemberProfileAccount account = memberAccountRepository.getAccount(memberId);
        Assert.isTrue(account.getEggQuantity() >= product.getEggQuantity(), "兑换失败:鸡蛋数量不足");
        // 获取收货地址
        OrderAddress orderAddress = addressRepository.readOrderAddress(memberId);
        EggOrderState state = ObjectUtil.isNotNull(orderAddress) ? EggOrderState.T10 : EggOrderState.T0;
        MemberView memberView = new MemberView().setId(memberId);
        UnionEggOrder unionEggOrder = new UnionEggOrder().setEggQuantity(product.getEggQuantity())
                .setTitle(product.getTitle())
                .setPostFee(product.getPostFee())
                .setMember(memberView).setState(state)
                .setExpressFee(BigDecimal.ZERO)
                .setAddress(orderAddress).setSubmitTime(LocalDateTime.now());
        unionEggOrder.insert();

        // 修改兑换数量
        product.setExQuantity(product.getExQuantity() + 1).update();
        // 修改会员鸡余额
        account.setEggQuantity(account.getEggQuantity() - product.getEggQuantity()).update();
        // 修改会员金币流水账
        memberAccountRepository.saveEvent(memberId,
                CoinAccountEvent.EXPRESS,
                product.getPostFee() ,
                "提取"+product.getTitle()+"支付运费");
        remindService.sendWhenEggOrderCreate(memberId,  unionEggOrder);



    }

    public void updateEggOrderAddress(Long memberId, OrderBody.UpdateAddressBody body) {
        UnionEggOrder record = new QUnionEggOrder().id.eq(body.getId()).member.id.eq(memberId).setMaxRows(1).findOne();
        Assert.notNull(record, "订单不存在");
        Assert.equals(EggOrderState.T0, record.getState(), "当前订单禁止修改地址");
        record.setState(EggOrderState.T10).setAddress(body.getAddress()).update();

    }

    /**
     * 获取最近N个订单信息
     * */
    public List<EggOrderNotice> getLastOrder(Integer size) {
        return new QUnionEggOrder().setMaxRows(size).order().id.desc()
                .findStream().map(x -> new EggOrderNotice()
                        .setOrderId(x.getId())
                        .setProductName(x.getTitle())
                        .setNickName(x.getMember().getNickName())
                        .setEggQuantity(x.getEggQuantity())
                        .setSubmitTime(x.getSubmitTime()))
                .collect(Collectors.toList());
    }


    /**
     * 完善订单快递信息
     * */
    public  void replenishExpress(RUnionEggOrder.ReplenishExpress body) {
        UnionEggOrder record = new QUnionEggOrder().id.eq(body.getId()).setMaxRows(1).findOne();
        Assert.notNull(record, "订单不存在");
        Assert.equals(EggOrderState.T10, record.getState(), "当前订单禁止发货");
        BeanUtil.copyProperties(body, record);
        record.setState(EggOrderState.T20).setSendTime(LocalDateTime.now()).update();
        remindService.sendWhenEggOrderReplenishExpress(record);
    }
}
